package handler

import (
	"context"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"gorm.io/gorm"
	"kuangstudy-mall/srvs/user-srv/global"
	"kuangstudy-mall/srvs/user-srv/model"
	"kuangstudy-mall/srvs/user-srv/proto"
	"kuangstudy-mall/srvs/user-srv/utils"
	"time"
)

type UserServiceHandler struct {
}

/**
 * 查询用户并分页
 * @author feige
 * @date 2024-04-08
 * @version 1.0
 * @desc
 */
func (handler *UserServiceHandler) FindUserList(ctx context.Context, req *proto.PageInfo) (*proto.UserListResponse, error) {
	var users []model.User
	var total int64
	results := global.DB.Raw("select count(1) from ksd_users").Count(&total)
	if results.Error != nil {
		return nil, results.Error
	}
	// 查询分页
	global.DB.Scopes(Paginate(int(req.PageNo), int(req.PageSize))).Find(&users)

	userListResponse := &proto.UserListResponse{}
	userListResponse.Total = total
	for _, user := range users {
		userInfoResponse := handler.transferToUserInfoResponse(user)
		userListResponse.Data = append(userListResponse.Data, &userInfoResponse)
	}

	return userListResponse, nil
}

func (handler *UserServiceHandler) GetUserByTelephone(ctx context.Context, req *proto.TelephoneRequest) (*proto.UserInfoResponse, error) {
	var user model.User
	results := global.DB.Where(&model.User{Mobile: req.Telephone}).First(&user)
	if results.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "用户不存在!!")
	}
	if results.Error != nil {
		return nil, results.Error
	}
	userInfoResponse := handler.transferToUserInfoResponse(user)
	return &userInfoResponse, nil
}

func (handler *UserServiceHandler) GetUserById(ctx context.Context, req *proto.IdRequest) (*proto.UserInfoResponse, error) {
	var user model.User
	results := global.DB.First(&user, req.Id)
	if results.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "用户不存在!!")
	}
	if results.Error != nil {
		return nil, results.Error
	}
	userInfoResponse := handler.transferToUserInfoResponse(user)
	return &userInfoResponse, nil
}

/**
 * 注册
 * @author feige
 * @date 2024-04-08
 * @version 1.0
 * @desc
 */
func (handler *UserServiceHandler) SaveUser(ctx context.Context, req *proto.CreateUserRequest) (*proto.UserInfoResponse, error) {
	var user model.User
	// 判断用户输入的手机号码是否已经被注册，如果注册就直接返回，用户已已经存在
	results := global.DB.Where(&model.User{Mobile: req.Mobile}).First(&user)
	if results.RowsAffected > 0 {
		return nil, status.Errorf(codes.AlreadyExists, "用户手机已被注册!!!")
	}

	birthDay := time.Unix(int64(req.BirthDay), 0)
	user.Mobile = req.Mobile
	user.NickName = req.NickName
	user.Birthday = &birthDay
	user.Password = utils.PasswordEncoder(req.PassWord)
	result := global.DB.Create(&user)
	if result.Error != nil {
		return nil, status.Errorf(codes.Internal, result.Error.Error())
	}
	userInfoResponse := handler.transferToUserInfoResponse(user)
	return &userInfoResponse, nil
}

func (handler *UserServiceHandler) UpdateUser(ctx context.Context, req *proto.UpdateUserRequeest) (*proto.BooleanResponse, error) {
	var user model.User
	// 判断用户输入的手机号码是否已经被注册，如果注册就直接返回，用户已已经存在
	results := global.DB.First(&user, req.Id)
	if results.RowsAffected == 0 {
		return nil, status.Errorf(codes.AlreadyExists, "用户不存在!!!")
	}

	birthDay := time.Unix(int64(req.BirthDay), 0)
	user.Mobile = req.Mobile
	user.NickName = req.NickName
	user.Birthday = &birthDay
	// 执行更新
	result := global.DB.Save(&user)
	// 如果执行失败就返回
	if result.Error != nil {
		return nil, status.Errorf(codes.Internal, result.Error.Error())
	}
	// 如果执行成功，使用BooleanResponse返回
	response := proto.BooleanResponse{}
	response.Success = result.RowsAffected > 0
	return &response, nil
}

/**
 * 密码验证
 * @author feige
 * @date 2024-04-08
 * @version 1.0
 * @desc
 */
func (handler *UserServiceHandler) CheckPassword(ctx context.Context, req *proto.PasswordCheckRequest) (*proto.CheckResponse, error) {
	verfiy := utils.PasswordVerfiy(req.Password, req.EncodePassword)
	return &proto.CheckResponse{Success: verfiy}, nil
}

/**
 * 参考官方文档：https://gorm.io/zh_CN/docs/scopes.html
 * 分页信息
 * @author feige
 * @date 2024-04-07
 * @version 1.0
 * @desc
 */
func Paginate(page int, pageSize int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if page == 0 {
			page = 1
		}

		switch {
		case pageSize > 100:
			pageSize = 100
		case pageSize <= 0:
			pageSize = 10
		}

		offset := (page - 1) * pageSize
		return db.Offset(offset).Limit(pageSize)
	}
}

func (handler *UserServiceHandler) transferToUserInfoResponse(user model.User) proto.UserInfoResponse {
	userInfoResponse := proto.UserInfoResponse{
		Id:       user.ID,
		PassWord: user.Password,
		Mobile:   user.Mobile,
		NickName: user.NickName,
		Gender:   user.Gender,
		Role:     int32(user.Role),
	}
	if user.Birthday != nil {
		userInfoResponse.BirthDay = uint64(user.Birthday.Unix())
	}
	return userInfoResponse
}
